package com.baigt.j8.stream;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream常用Api
 */
public class StreamApiDemo {
    public static void main(String[] args) {
//        createStreamWithDirectWay();
//        createStreamWithOtherWay();
        List<StreamEntity> list = Arrays.asList(new StreamEntity(), new StreamEntity(), new StreamEntity(), new StreamEntity());
//        IntermediateOperate(list);
//        terminalOperate(list);
//        terminalOperateOfForEach();
//        terminalOperateShort();
        terminalJoin();
    }

    /**
     * 直接的方式
     */
    public static void createStreamWithDirectWay() {
        System.out.println("方式1");
        Stream.builder().add("111").add("222").build().forEach(System.out::println);
        System.out.println("方式2");
        System.out.println(Stream.empty().count());
        System.out.println("方式3");
        Stream.generate(StreamEntity::new).limit(2).forEach(System.out::println);
        System.out.println("方式4");
        Stream.iterate(2, seed -> seed * 2).limit(2).forEach(System.out::println);
        System.out.println("方式5");
        Stream.of("Hello", "baigt").forEach(System.out::println);
    }

    /**
     * 间接的方式，以及流的数据来源
     */
    public static void createStreamWithOtherWay() {
        System.out.println("方式1- 数组");
        Arrays.stream(new int[]{1, 2, 4}).forEach(System.out::println);
        System.out.println("方式2 - 集合");
        Arrays.asList("1", "2", "3").stream();
        Collections.EMPTY_LIST.stream();
        System.out.println("方式3 - io流");
        try {
//            Files.lines(Paths.get("D:\\IdeaProjects\\course\\src\\main\\java\\com\\ricky\\j8\\stream\\StreamDemo.java"), Charset.defaultCharset()).forEach(System.out::println);
            Files.lines(Paths.get("D:\\IdeaProjects\\course\\src\\main\\java\\com\\ricky\\j8\\stream\\StreamDemo.java"), Charset.defaultCharset()).forEach(System.out::println);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("方式4 - generator function  may not this ,maybe Stream.generate");
        StreamGenerateFunction<String> function = (r) -> Arrays.asList(r).stream();
        function.get("1").forEach(System.out::println);
    }

    /**
     * 中间操作
     * filter
     * sort
     * limit
     * skip
     * distinct
     * map
     * flatmap
     */
    public static void IntermediateOperate(List<StreamEntity> list) {
        list.stream().forEach(System.out::println);
        // 过滤 年龄大于3的  接收一个Predicate
        list.stream().filter(streamEntity -> {
            return streamEntity.getAge() > 3;
        });
        System.out.println("--------------");
        //年龄升序   接收一个 Comparator
        list.stream().sorted((s1, s2) -> {
            return s1.getAge() - s2.getAge();
        }).forEach(System.out::println);

        System.out.println("-----只取一个--------");
        list.stream().limit(1).forEach(System.out::println);
        System.out.println("-----跳过前两个------");
        list.stream().skip(2).forEach(System.out::println);
        System.out.println("-----去除重复记录------" + list.size());
        list.stream().distinct().forEach(System.out::println);
        System.out.println("-----分组------");
        //接收一个 Function函数  转换为int集合
        Stream<Integer> integerStream = list.stream().map(StreamEntity::getAge);
        integerStream.forEach(System.out::println);

        System.out.println("-----flatMap------");
        list.forEach(s -> {
            s.setSubs(Arrays.asList(new StreamEntiySub(), new StreamEntiySub(), new StreamEntiySub()));
        });
        // 传入ggwhstream流
        List<Integer> collect = list.stream().flatMap(streamEntity -> streamEntity.getSubs().stream()).map(s -> s.getPrice()).collect(Collectors.toList());
        System.out.println(collect);
    }

    /*
     * 终端操作
     * foreach
     * collect
     * findXxx
     * XxxMatch
     * count
     * sum
     * max
     * min
     * */
    public static void terminalOperate(List<StreamEntity> list) {
        // 接收一个Consumer对象  返回void对象  打印list中的没有一个元素
        list.stream().forEach(System.out::println);
        System.out.println("----------------");
        list.stream().forEachOrdered(System.out::println);
        System.out.println("----------------");
        // 接收一个 Collector
        list.stream().filter(entity -> entity.getSubs() != null && entity.getSubs().size() > 0).collect(Collectors.toList());
//        Supplier<R> supplier,  BiConsumer<R, ? super T> accumulator,  BiConsumer<R, R> combiner
        //
        list.stream().filter(entity -> entity.getSubs() != null && entity.getSubs().size() > 0).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);


    }

    public static void terminalOperateOfForEach() {
        // 在并行的时候不保证顺序
        Stream.of("AAA", "BBB", "CCC").parallel().forEach(s -> System.out.println("forEach:" + s));
        // 在并行的时候保证顺序
        Stream.of("AAA", "BBB", "CCC").parallel().forEachOrdered(s -> System.out.println("ForEachOrder:" + s));
    }

    /**
     *
     * 类似 && 和|| 的操作
     * // java PHP  3
     */
    public static void terminalOperateShort() {
        // 流的短路操作
        List<String> list = Arrays.asList("java", "PHP", "python", "net");
        list.stream().mapToInt(s->{
            System.out.println(s);
            return s.length();
        }).filter(t->t==3).findFirst().ifPresent(System.out::println);
        // 打印结果是什么？

    }

    public static void terminalJoin() {
        List<String> says = Arrays.asList("Hi", "Hello", "你好");
        List<String> names = Arrays.asList("baigt", "shiy", "handd");
//        names.stream().flatMap(say->says.stream().map(name->say+","+name)).forEach(System.out::println);
        says.stream().flatMap(say->names.stream().map(name->say+","+name)).forEach(System.out::println);
    }

}

class StreamEntity {
    private String name = "name" + new Random().nextInt(10);
    private int age = new Random().nextInt(10);
    private List<StreamEntiySub> subs;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<StreamEntiySub> getSubs() {
        return subs;
    }

    public void setSubs(List<StreamEntiySub> subs) {
        this.subs = subs;
    }

    @Override
    public String toString() {
        return "StreamEntity{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class StreamEntiySub {
    private String seId = "seId" + new Random().nextInt(10);
    private Integer price = new Random().nextInt(10);

    public String getSeId() {
        return seId;
    }

    public void setSeId(String seId) {
        this.seId = seId;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "StreamEntiySub{" +
                "seId='" + seId + '\'' +
                ", price='" + price + '\'' +
                '}';
    }


}

class StreamEntity01 {
    private String name;
    private Integer age;

    public StreamEntity01(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "StreamEntity01{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public static void main(String[] args) {
        List<StreamEntity01> streamEntity01s = Arrays.asList(new StreamEntity01("baigt", 30), new StreamEntity01("baigt01", 30), new StreamEntity01("baigt02", 40), new StreamEntity01("baigt07", 50), new StreamEntity01("baigt04", 90));
        Map<Boolean, List<StreamEntity01>> booleanListMap = streamEntity01s.stream().collect(Collectors.partitioningBy(entity01 -> entity01.getAge() > 30));
        Arrays.asList(1,2,3).stream().sorted(Integer::compareTo);
    }
}
interface StreamGenerateFunction<T> {
    Stream<String> get(T t);
}
